package com.winit.openapi.es.manager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;

import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.winit.openapi.es.util.ElasticUtils;
import com.winit.openapi.es.vo.EsResultVo;
import com.winit.openapi.es.vo.Index;
import com.winit.openapi.es.vo.SpanQuery;

/**
 * 开发者平台同步监控平台错误信息类
 * 
 * @version <pre>
 * Author	Version		Date		Changes
 * minghao.deng 	1.0  		2018年2月1日 	Created
 *
 * </pre>
 * @since 1.
 */
@Service("esExceptionManager")
public class EsExceptionManager {

    private Logger         logger = LoggerFactory.getLogger(EsExceptionManager.class);

    @Resource
    private Client         esClient;

    @Resource
    private EsAdminManager esAdminManager;

    public List<EsResultVo> queryExceptionList(SpanQuery query) {

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("timestamp")
            .from(query.getStartTimestamp())
            .to(query.getEndTimestamp()));

        String[] indexs = ElasticUtils.buildIndex(Index.exception.name(), query.getStartDate(), query.getEndDate());

        indexs = esAdminManager.queryAllValidIndexName(indexs);

        if (null == indexs || indexs.length == 0) {
            logger.warn("同步平台错误码信息返回为空。" + queryBuilder.toString());
            return Collections.emptyList();
        }

        SearchRequestBuilder searchRequest = esClient.prepareSearch(indexs);

        searchRequest.setQuery(queryBuilder)
            .setFetchSource(true)
            .addSort("timestamp", SortOrder.DESC)
            .setFrom(query.getOffset())
            .setSize(query.getLimit())
            .setExplain(true);

        searchRequest.setQuery(queryBuilder)
            .setFetchSource(false)
            .addAggregation(AggregationBuilders.terms("byErrorCode")
                .field("data.errorCode")
                .size(Integer.MAX_VALUE)
                .subAggregation(AggregationBuilders.terms("byApiName")
                    .field("data.apiName")
                    .subAggregation(AggregationBuilders.terms("byVersion")
                        .field("data.version")
                        .subAggregation(AggregationBuilders.terms("byErrorDesc").field("data.errorDesc")))));

        SearchResponse response = searchRequest.execute().actionGet();

        Terms errorTerms = response.getAggregations().get("byErrorCode");
        Terms apiNameTerms = null;
        Terms errorDescTerms = null;
        Terms versionTerms = null;
        List<EsResultVo> result = new ArrayList<EsResultVo>();
        if (errorTerms == null || errorTerms.getBuckets().isEmpty()) {

            logger.warn("同步平台错误码根据输入条件为查询结果为空" + queryBuilder.toString());
            return Collections.emptyList();
        }

        for (Terms.Bucket errorBuk : errorTerms.getBuckets()) {

            EsResultVo vo = new EsResultVo();
            List<String> actionList = new ArrayList<String>();
            vo.setErrorCode(errorBuk.getKeyAsString());
            // 二级分组的内容:错误码所对应的action名称
            apiNameTerms = errorBuk.getAggregations().get("byApiName");
            if (apiNameTerms == null || apiNameTerms.getBuckets().isEmpty()) {
                continue;
            }
            for (Terms.Bucket api_buk : apiNameTerms.getBuckets()) {

                actionList.add(api_buk.getKeyAsString());
                vo.setActionList(actionList);

                versionTerms = api_buk.getAggregations().get("byVersion");
                if (versionTerms == null || versionTerms.getBuckets().isEmpty()) {
                    continue;
                }
                // 读取错误信息
                vo.setVersion(versionTerms.getBuckets().get(0).getKeyAsString());
                if (versionTerms.getBuckets().get(0).getAggregations() == null) {
                    vo.setErrorDesc(null);
                    continue;
                }

                errorDescTerms = versionTerms.getBuckets().get(0).getAggregations().get("byErrorDesc");

                if (null != errorDescTerms && errorDescTerms.getBuckets().size() > 0) {

                    String desc = errorDescTerms.getBuckets().get(0).getKeyAsString();
                    StringBuffer buffer = new StringBuffer(desc);
                    try {
                        if (desc.contains("[") || desc.contains("]") || desc.contains("【") || desc.contains("】")) {
                            // 替换掉占位符[]里面的内容
                            String descFormat = desc.replaceAll("(【|\\[).*?(\\]|】)", "[]");
                            buffer.append(descFormat);
                        }
                    } catch (Exception e) {
                        logger.warn("替换错误异常信息失败，原始信息：" + desc);
                        vo.setErrorDesc(desc);
                    }

                    vo.setErrorDesc(buffer.toString());
                }

            }
            result.add(vo);
        }

        return result;
    }

}
